﻿// This code is released under the BSD license.
namespace PugLib
{
    using System;
    using System.Threading;

    #region Interface

    /// <summary>
    /// Provides options for a repeating method call
    /// </summary>
    public interface IRepeatOptions
    {
        /// <summary>
        /// Set the repeater to call the method in a background thread.
        /// </summary>
        /// <exception cref="InvalidOperationException">If this property is called more than once for this instance.</exception>
        IRepeatOptions InBackgroundThread { get; }

        /// <summary>
        /// Set the repeater to stop when the call fails, and throw the exception.
        /// </summary>
        /// <exception cref="InvalidOperationException">If this property is called more than once for this instance.</exception>
        IRepeatOptions OnExceptionThrow { get; }

        /// <summary>
        /// Set the repeater to stop when the call fails.
        /// </summary>
        /// <exception cref="InvalidOperationException">If this property is called more than once for this instance.</exception>
        IRepeatOptions UntilFails { get; }

        /// <summary>
        /// Set the repeater to stop when the call succeeds.
        /// </summary>
        /// <exception cref="InvalidOperationException">If this property is called more than once for this instance.</exception>
        IRepeatOptions UntilSucceeds { get; }

        /// <summary>
        /// Set the <see cref="ThreadPriority"/> of the thread that will invoke the method.
        /// </summary>
        /// <param name="priority">The thread priority.</param>
        /// <exception cref="InvalidOperationException">If this method is called more than once for this instance.</exception>
        IRepeatOptions At(ThreadPriority priority);

        /// <summary>
        /// Sets the repeater to call a method, or a set of methods, upon failure.
        /// This option can be set multiple times and all the methods will be called at the specified order.
        /// If no method is set with this method, then all exceptions will be thrown to the calling thread.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <exception cref="ArgumentNullException">if the method is null.</exception>
        IRepeatOptions OnExceptionCall(Action<Exception> method);

        /// <summary>
        /// Sets the repeater to call a method, or a set of methods, upon success.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <exception cref="ArgumentNullException">if the method is null.</exception>
        IRepeatOptions OnSuccessCall(Action method);

        /// <summary>
        /// Sets the repeater to call a method when it finishes the whole process successfuly.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <exception cref="ArgumentNullException">if the method is null.</exception>
        IRepeatOptions OnFinishCall(Action method);

        /// <summary>
        /// set the parameters that will be passed to the method.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <exception cref="InvalidOperationException">If this method is called more than once for this instance.</exception>
        IRepeatOptions WithParameters(params object[] parameters);

        /// <summary>
        /// Set the repeater to pause between each call.
        /// </summary>
        /// <param name="milliseconds">The milliseconds.</param>
        /// <exception cref="InvalidOperationException">If this method is called more than once for this instance.</exception>
        /// <exception cref="ArgumentOutOfRangeException">If the milliseconds is less than zero.</exception>
        IRepeatOptions PauseBetweenCalls(int milliseconds);

        /// <summary>
        /// Starts the repeater and repeater the call the given amount of times.
        /// </summary>
        /// <param name="times">The times to repeater the call.</param>
        void Start(int times);

        /// <summary>
        /// Starts the repeater and repeater the call forever.
        /// </summary>
        void Start();
    }

    #endregion Interface
}